/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * @brief map-messenger /map-messenger/include/GuiInterface.h
 * Copyright (C) Matheus Neder, Amanda Duarte, Priscila Cardoso 2010
 * 
 * GuiInterface.h is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GuiInterface.h is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * @brief map-messenger /map-messenger/include/GuiInterface.h
 * @file GuiInterface.h
 * @date 06/06/2010
 * @author Matheus Neder <matheusneder@gmail.com>
 * @author Amanda Duarte <mandinhaduarte89@gmail.com>
 * @author Priscila Cardoso <japinha-htinha@hotmail.com>
 */

#ifndef GUIINTERFACE_H_
#define GUIINTERFACE_H_

#include <cstdlib>
#include <libglademm/xml.h>
#include <gtkmm.h>
#include <iostream>
#include "MapSocket.h"

#define GLADE_FILE "gui/interface.glade"

class GuiInterface
{
	Gtk::Window* mainWindow;
	Gtk::TextView* chatAreaTextView;
	Gtk::TextView* messageWriterAreaTextView;
	Gtk::Button* sendButton;
	Gtk::ScrolledWindow* chatAreaScroll;
	Gtk::ImageMenuItem* fileMenuItemExit;
	Gtk::ImageMenuItem* helpMenuItemAbout;
	Gtk::AboutDialog* aboutDialog;
	//Gtk::Assistant* connectionAssitant;

	Glib::RefPtr<Gtk::TextBuffer> chatAreaTextBuffer;
	Glib::RefPtr<Gtk::TextBuffer::TagTable> chatAreaTextBufferTagTable;
	Glib::RefPtr<Gtk::TextBuffer> messageWriterAreaTextBuffer;

	Glib::RefPtr<Gnome::Glade::Xml> refXml;

	MapSocket* conn;

public:
	Gtk::Window* getMainWindow() const
	{
		return mainWindow;
	}

//	Gtk::Assistant* getConnectionAssitant() const
//	{
//		return connectionAssitant;
//	}

	Gtk::TextView* getChatAreaTextView() const
	{
		return chatAreaTextView;
	}

	Glib::RefPtr<Gtk::TextBuffer> getChatAreaTextBuffer() const
	{
		return chatAreaTextBuffer;
	}

	inline bool isChatAreaTextBufferEmpty() const
	{
		return (chatAreaTextBuffer->begin() == chatAreaTextBuffer->end());
	}

	inline bool isChatAreaScrolledDown() const
	{
		Gtk::Adjustment* vadj = chatAreaScroll->get_vadjustment();
		return ((vadj->get_upper() - vadj->get_value())
				== vadj->get_page_size())
				|| !chatAreaScroll->get_vscrollbar_visible();
	}

	void chatAreaScrollDown()
	{
		Gtk::Adjustment* vadj = chatAreaScroll->get_vadjustment();
		vadj->set_value(vadj->get_upper());
	}

	void chatAreaInsertMessage(const Glib::ustring& from,
			const Glib::ustring& text)
	{
		using namespace std;
		bool wasChatAreaScrolledDown = isChatAreaScrolledDown();
		if (!isChatAreaTextBufferEmpty())
		{
			chatAreaTextBuffer->insert(chatAreaTextBuffer->end(), "\n");
		}
		chatAreaTextBuffer->insert_with_tag(chatAreaTextBuffer->end(), from
				+ ": ", "bold");
		chatAreaTextBuffer->insert(chatAreaTextBuffer->end(), text);
		if (wasChatAreaScrolledDown)
		{
			chatAreaScrollDown();
		}

	}

	bool mainWindowOnDeleteEvent(GdkEventAny* event)
	{
		Gtk::Main::quit();
		exit(0);
		return true;
	}

	explicit GuiInterface(MapSocket& conn) throw (Gnome::Glade::XmlError) :
		mainWindow(NULL), chatAreaTextView(NULL), conn(&conn)
	{
		refXml = Gnome::Glade::Xml::create(GLADE_FILE);
		refXml->get_widget("mainWindow", mainWindow);
		refXml->get_widget("chatAreaTextView", chatAreaTextView);
		refXml->get_widget("messageWriterAreaTextView",
				messageWriterAreaTextView);
		refXml->get_widget("sendButton", sendButton);
		refXml->get_widget("chatAreaScroll", chatAreaScroll);
		refXml->get_widget("fileMenuItemExit", fileMenuItemExit);
		refXml->get_widget("helpMenuItemAbout", helpMenuItemAbout);
		refXml->get_widget("aboutDialog", aboutDialog);
		//refXml->get_widget("connectionAssitant", connectionAssitant);
		chatAreaTextBuffer = chatAreaTextView->get_buffer();
		messageWriterAreaTextBuffer = messageWriterAreaTextView->get_buffer();

		chatAreaTextBufferTagTable = chatAreaTextBuffer->get_tag_table();
		Glib::RefPtr<Gtk::TextBuffer::Tag> refTagBold =
				Gtk::TextBuffer::Tag::create("bold");
		refTagBold->property_weight() = Pango::WEIGHT_BOLD;
		chatAreaTextBufferTagTable->add(refTagBold);

		mainWindow->signal_delete_event().connect(sigc::mem_fun(*this,
				&GuiInterface::mainWindowOnDeleteEvent));
		fileMenuItemExit->signal_activate().connect(sigc::mem_fun(*this,
				&GuiInterface::fileMenuItemExitOnActivate));
		helpMenuItemAbout->signal_activate().connect(sigc::mem_fun(*this,
				&GuiInterface::helpMenuItemAboutOnActivate));
		sendButton->signal_clicked().connect(sigc::mem_fun(*this,
				&GuiInterface::sendButtonOnClick));
		messageWriterAreaTextView->signal_key_press_event().connect_notify(
				sigc::mem_fun(*this,
						&GuiInterface::messageWriterAreaTextViewOnKeyPress));
		messageWriterAreaTextView->signal_key_release_event().connect(
				sigc::mem_fun(*this,
						&GuiInterface::messageWriterAreaTextViewOnKeyRelease));
		//mainWindow->signal_focus().connect(*this, &GuiInterface::mainWindowOnFocus);
		mainWindow->signal_focus_in_event().connect_notify(sigc::mem_fun(*this,
				&GuiInterface::mainWindowOnFocusInEvent));
		//aboutDialog->signal_button_press_event().connect_notify();
		//		aboutDialog->signal_button_release_event().connect(
		//				sigc::mem_fun(*this, &GuiInterface::aboutDialogOnButtonRelease));
		aboutDialog->signal_response().connect(sigc::mem_fun(*this,
				&GuiInterface::aboutDialogOnResponse));
	}

	void aboutDialogOnResponse(int responseId)
	{
		aboutDialog->hide();
	}

	void mainWindowOnFocusInEvent(GdkEventFocus* event)
	{
		mainWindow->set_urgency_hint(false);
	}

	void fileMenuItemExitOnActivate()
	{
		Gtk::Main::quit();
		exit(0);
	}

	void helpMenuItemAboutOnActivate()
	{
		aboutDialog->show();
	}

	static const guint ENTER_KEYVAL = 65293;
	static const guint TAB_KEYVAL = 65289;

	void messageWriterAreaTextViewOnKeyPress(GdkEventKey* event)
	{
		switch (event->keyval)
		{
		case ENTER_KEYVAL:
			if (!isMessageWriterAreaTextBufferEmpty())
				sendButtonOnClick();
			messageWriterAreaTextView->set_editable(false);
			break;
		case TAB_KEYVAL:
			messageWriterAreaTextView->set_editable(false);
			break;
		}
	}

	inline bool isMessageWriterAreaTextBufferEmpty() const
	{
		return (messageWriterAreaTextBuffer->begin()
				== messageWriterAreaTextBuffer->end());
	}

	bool messageWriterAreaTextViewOnKeyRelease(GdkEventKey* event)
	{
		sendButton->set_sensitive(!isMessageWriterAreaTextBufferEmpty());
		messageWriterAreaTextView->set_editable(true);
		return true;
	}

	void sendButtonOnClick()
	{
		Glib::ustring message;
		message = messageWriterAreaTextBuffer->get_text();
		chatAreaInsertMessage("eu", message);
		chatAreaScrollDown();
		messageWriterAreaTextBuffer->set_text("");
		MapSocket::write(conn->getSocketPtr(), message.c_str());
	}

	Gtk::MessageDialog::MessageDialog* fatalErrorDialog(
			const Glib::ustring& message)
	{
		Gtk::MessageDialog::MessageDialog* errorDialog =
				new Gtk::MessageDialog::MessageDialog(message, false,
						Gtk::MESSAGE_ERROR);
		errorDialog->signal_response().connect(sigc::mem_fun(*this,
				&GuiInterface::fatalErrorDialogOnResponse));
		errorDialog->show();
		return errorDialog;
	}

	void fatalErrorDialogOnResponse(int responseId)
	{
		Gtk::Main::quit();
		exit(1);
	}

public:

	virtual ~GuiInterface();
	Gtk::TextView *getMessageWriterAreaTextView() const;
	Gtk::Button *getSendButton() const;
	Glib::RefPtr<Gtk::TextBuffer> getMessageWriterAreaTextBuffer() const;
	Gtk::ScrolledWindow *getChatAreaScroll() const;
};

#endif /* GUIINTERFACE_H_ */
